/*
 * Copyright (c) 2011 Anthony Vandikas
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 
 * files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, 
 * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software 
 * is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 
 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#pragma once
#include "AbstractHistory.h"

/**
 * An implementation of the AbstractHistory class that
 * uses an SQL database as a backend.
 */
class DatabaseHistory :	public AbstractHistory
{
	Q_OBJECT

public:
	/**
	 * Constructs a DatabaseHistory.
	 * Data from previous runnings will be loaded (if any).
	 */
	DatabaseHistory();

	/**
	 * Clears the database of all entries.
	 */
	void clear() override;

	/**
	 * Records a new entry to the database.
	 * The date/time cannot be specified - it is typically obtained from the current date and time.
	 *
	 * @param student The student who is recording the entry.
	 * @param item The item being signed out.
	 */
	void record(const Student &student, const Item &item) override;

	/**
	 * Returns all entries in the database that meet the specified criteria.
	 *
	 * @param minDate The minimum date for which all returned entries must have been recorded on or after.
	 * @param maxDate The maximum date for which all returned entries must have been recorded on or before.
	 * @param studentKeywords The search terms for the student.
	 * @param itemKeywords The search terms for the item.
	 */
	QList<Entry> filter(const QDate &minDate, const QDate &maxDate, const QStringList &studentKeywords, const QStringList &itemKeywords);
	
private:
	/**
	 * Creates a query for filtering results from a database.
	 *
	 * @param minDate The minimum date for which all returned entries must have been recorded on or after.
	 * @param maxDate The maximum date for which all returned entries must have been recorded on or before.
	 * @param studentKeywords The search terms for the student.
	 * @param itemKeywords The search terms for the item.
	 */
	QSqlQuery createFilterQuery(const QDate &minDate, const QDate &maxDate, const QStringList &studentKeywords, const QStringList &itemKeywords) const;
	
	/**
	 * Creates a query string for filtering results from a database.
	 * The result contains placeholder values to be bound at a later time.
	 *
	 * @param studentKeywordCount The number of student keyword filters.
	 * @param itemKeywordCount The number of item keyword filters.
	 */
	QString createFilterQueryString(int studentKeywordCount, int itemKeywordCount) const;

	/**
	 * Bind the date restriction (minDate < dateTime < maxDate) to the query.
	 *
	 * @param query The query to bind.
	 * @param minDate The lower bound of the restriction.
	 * @param maxDate The upper bound of the restriction.
	 */
	void bindDateRestriction(QSqlQuery &query, const QDate &minDate, const QDate &maxDate) const;
	
	/**
	 * Bind the keyword restrictions (students/items must contain these keywords) to the query.
	 *
	 * @param query The query to bind.
	 * @param studentKeywords The keywords the students must contain.
	 * @param itemKeywords The keywords the items must contain.
	 */
	void bindKeywords(QSqlQuery &query, const QStringList &studentKeywords, const QStringList &itemKeywords) const;

	/**
	 * Extracts a list of entries from the output of a previously executed query.
	 */
	QList<Entry> extractOutput(QSqlQuery &query) const;

	/**
	 * Extracts an entry stored in an SQL record.
	 */
	Entry extractEntry(QSqlRecord &record) const;

	QSqlDatabase database;
};
